#ifndef OBJMODEL_H_
#define OBJMODEL_H_

#include "irrlicht.h"
#include "IrrNewt.hpp"

#include "../Logger.h"

#include <string>
#include <iostream>

namespace Facets {

	using namespace irr;

	class ObjModel {
			// this has a mesh (or set of meshes) for irrlicht
			//scene::IAnimatedMeshSceneNode* m_MeshSceneNode;
			newton::ICharacterController* m_Model;
			core::stringc m_ModelXMLName;
			static core::array<newton::IBody*> s_NonCollisionObjects;
			float m_AnimSpeed;
			float m_Mass;
						
			scene::ITextSceneNode* m_nameNode;
			
			// Should we ignore this object when checking collisions?
			bool m_NonCollision;
			
			// Should the object be able to rotate around the Y axis?
			bool m_LockRotation;
									
			void loadModel(const core::stringc& filename);
			void applyTextureToModel(int matnum, const core::stringc& filename);
			void setAnimationSpeed();
			
		public:
			ObjModel(const core::stringc& mxml);
			virtual ~ObjModel();

			void changeModel(const core::stringc& mxml);
			
			void setNonCollision() {
				if(!m_NonCollision) 
					s_NonCollisionObjects.push_back(m_Model);
				m_NonCollision = true;
			}
			
			/**
			 * Sets the position of the scene getNode().
			 * @param pos The position vector for placing it in the world.
			 */
			inline void setPosition(const core::vector3df& pos) {
				m_Model->setPosition(pos);
			}

			/**
			 * Gets position of the scene getNode().
			 * @return Returns the position of the model/getNode().
			 */
			inline const core::vector3df& getPosition() const {
				return m_Model->getPosition();
			}


			/**
			 * Sets the position of the scene getNode().
			 * @param pos The position vector for placing it in the world.
			 */
			inline void setDirection(const core::vector3df& dir) {
				m_Model->setRotation(dir);
			}

			/**
			 * Gets direction of the scene getNode().
			 * @return Returns the direction of the model/getNode().
			 */
			inline const core::vector3df& getDirection() const {
				return m_Model->getNode()->getRotation();
			}
			
			inline void moveForward(float speed) {
				moveLateral(speed);
			}

			inline void moveBackward(float speed) {
				moveLateral(-speed);
			}

			void moveLateral(float multiplier);
			
			inline void turnLeft(float speed) {
				turn(-speed);
			}

			inline void turnRight(float speed) {
				turn(speed);
			}
			
			void turn(float speed);
			
			inline void stopMoving() {
				core::vector3df tmp = m_Model->getVelocity();
				tmp.X = tmp.Z = 0;
				m_Model->setVelocity(tmp);
			}
			
			/**
			 * Sets animation if the model is md2. Will add type-checking
			 * later.
			 */ 
			inline void setAnimation(scene::EMD2_ANIMATION_TYPE animtype) {
				(dynamic_cast<scene::IAnimatedMeshSceneNode*>(m_Model->getNode()))->setMD2Animation(animtype);
				setAnimationSpeed();
			}
			
			inline void updateWeight(const float& weight) {
				m_Model->setForce(core::vector3df(0,0,0));
				m_Mass = weight;
				m_Model->setMass(weight);
				m_Model->addForceContinuous(core::vector3df(0,-64.0f*(m_Mass),0));		
			}
			
			inline void update(const float& dt) {
				__update();
			}
			inline void update() {
				__update();
			}
			
			virtual void __update(const float& dt = 0);

			
			void createNameNode(const core::stringc& name);
			
			void setNameVisible(bool vis);
			
			bool getNameVisible();			

			irr::scene::ISceneNode* getNode() {
				return m_Model->getNode();
			}
	};

}
	
#endif /*OBJMODEL_H_*/
